﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Infrastructure.Extensions
{
    /// <summary>
    /// 通用扩展方法工具类
    /// 提供基础类型转换、枚举处理、异常处理等扩展方法
    /// </summary>
    public static class CommonExtensions
    {
        //------------------------ 基础类型转换扩展 ------------------------//

        #region ParseToLong
        /// <summary>
        /// 将对象转换为 long 类型（转换失败返回 0）
        /// </summary>
        public static long ParseToLong(this object obj)
        {
            return long.TryParse(obj?.ToString(), out var result) ? result : 0L;
        }

        /// <summary>
        /// 将字符串转换为 long 类型（转换失败返回指定默认值）
        /// </summary>
        public static long ParseToLong(this string str, long defaultValue = 0)
        {
            return long.TryParse(str, out var result) ? result : defaultValue;
        }
        #endregion

        // 类似优化其他基础类型方法（如ParseToInt、ParseToDecimal等）
        // 使用 TryParse 替代 Parse + try/catch，提升性能
        // 统一参数命名（如 defaultValue 代替 result）

        #region ParseToInt
        /// <summary>
        /// 将对象转换为 int 类型
        /// </summary>
        public static int ParseToInt(this object value, int defaultValue = 0)
        {
            return int.TryParse(value?.ToString(), out var result) ? result : defaultValue;
        }
        #endregion

        //------------------------ 日期时间转换扩展 ------------------------//

        #region ParseToDateTime
        /// <summary>
        /// 将字符串解析为 DateTime（支持 yyyy/MM/dd 格式和紧凑格式）
        /// </summary>
        /// <param name="str">日期字符串（支持格式示例：2023、202305、20230525、2023052515 等）</param>
        /// <returns>解析失败返回 DateTime.MinValue</returns>
        public static DateTime ParseToDateTime(this string str)
        {
            if (string.IsNullOrWhiteSpace(str)) return DateTime.MinValue;

            // 统一使用不变文化避免区域格式问题
            var format = str.Contains("-") || str.Contains("/") ? "loose" : GetCompactDateTimeFormat(str.Length);

            return DateTime.TryParseExact(str, format, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out var result)
                ? result
                : DateTime.MinValue;
        }

        /// <summary>
        /// 根据紧凑格式字符串长度获取对应格式
        /// </summary>
        private static string GetCompactDateTimeFormat(int length) => length switch
        {
            4 => "yyyy",
            6 => "yyyyMM",
            8 => "yyyyMMdd",
            10 => "yyyyMMddHH",
            12 => "yyyyMMddHHmm",
            14 => "yyyyMMddHHmmss",
            _ => "yyyyMMddHHmmss" // 默认格式
        };
        #endregion

        //------------------------ 枚举处理扩展 ------------------------//

        #region EnumToDictionary
        /// <summary>
        /// 将枚举转换为字典（Key: 枚举值, Value: 描述或名称）
        /// </summary>
        /// <exception cref="ArgumentException">当类型不是枚举时抛出</exception>
        public static Dictionary<int, string> EnumToDictionary(this Type enumType)
        {
            if (!enumType.IsEnum)
                throw new ArgumentException("Type must be an Enum", nameof(enumType));

            return Enum.GetValues(enumType)
                .Cast<Enum>()
                .ToDictionary(
                    key => Convert.ToInt32(key),
                    value => value.GetDescription()
                );
        }
        #endregion

        #region GetDescription
        /// <summary>
        /// 获取枚举值的 Description 特性描述
        /// </summary>
        public static string GetDescription(this Enum enumValue)
        {
            var fieldInfo = enumValue.GetType().GetField(enumValue.ToString());
            var attribute = fieldInfo?.GetCustomAttribute<DescriptionAttribute>();
            return attribute?.Description ?? enumValue.ToString();
        }
        #endregion

        //------------------------ 异常处理扩展 ------------------------//

        #region GetOriginalException
        /// <summary>
        /// 获取最底层的原始异常（递归解包 InnerException）
        /// </summary>
        public static Exception GetOriginalException(this Exception ex)
        {
            return ex.InnerException == null ? ex : ex.InnerException.GetOriginalException();
        }
        #endregion

        //------------------------ 其他工具扩展 ------------------------//

        #region IsEmpty
        /// <summary>
        /// 检查对象是否为空或空字符串
        /// </summary>
        public static bool IsEmpty(this object value)
        {
            return string.IsNullOrWhiteSpace(value?.ToString());
        }
        #endregion
    }
}
